// 队列接口
export interface IUploadQueue {
  addTask(tasks: any[], groupId?: string | number): void
  start(): void

  pauseAll(): void
  resumeAll(): void
  pauseGroup(groupId: string | number): void
  resumeGroup(groupId: string | number): void
  // reset(): void
  onComplete(callback: () => void): void
}

/**
 * 分片并发队列
  @params concurrency 最大并发数
 *  */
class Queue implements IUploadQueue {
  // 最大并发数
  private concurrency: number
  // 当前运行中的请求数
  private running: number
  // 任务队列（FIFO）
  private queue: any[]
  // 任务组
  private taskGroups: Map<string, any>
  // 已完成请求列表
  private successTasks: any[]
  // 失败请求列表
  private failedTasks: any[]
  // 队列日志
  private LogList: string[] = []
  // 分片大小
  private chunkSize: number
  // 钩子
  private Hooks: any
  // 日志服务
  private LogService: any
  // 状态服务
  private StoreService: any
  // 请求服务
  private RequestService: any
  
  constructor(concurrency = 3, chunkSize = 1024 * 1024 * 10, hooks: any, LogService: any, StoreService: any, RequestService: any) {
    this.Hooks = hooks
    this.LogService = LogService
    this.StoreService = StoreService
    this.RequestService = RequestService
    // 最大并发数
    this.concurrency = concurrency

    this.running = 0 // 当前运行中的请求数
    this.queue = [] // 任务队列
    this.taskGroups = new Map()
    this.successTasks = [] // 已完成请求数
    this.failedTasks = [] // 失败请求数
    this.chunkSize = chunkSize

    // this.updateQueueStatus()
  }

  // 更新队列状态
  updateQueueStatus() {
    // debugger

    let queueTaskNum = 0
    // 已暂停文件列表
    let isPausedCount: number = 0
    // 已暂停任务列表
    let isPausedTaskCount: number = 0
    // 等待中文件列表
    let isActiveCount: number = 0
    // 等待中任务列表
    let isActiveTaskCount: number = 0

    Array.from(this.taskGroups.values()).forEach((item) => {
      // 已暂停文件列表
      if (item.groupStatus === 'paused') {
        isPausedCount += 1
        item.tasks.forEach((taskItem: any) => {
          isPausedTaskCount += 1
          queueTaskNum += 1
        })
      }
      // 等待中文件列表
      else if (item.groupStatus === 'active') {
        isActiveCount += 1
        item.tasks.forEach((taskItem: any) => {
          queueTaskNum += 1
          if (taskItem.taskStatus === 'pending') {
            isActiveTaskCount += 1
            // pending | running | success | failed
          }
        })
      }
    })

    // 记录队列总文件数
    this.StoreService.queueStatus.value.queueFileNum = this.taskGroups.size
    // 记录队列总任务数
    this.StoreService.queueStatus.value.queueTaskNum = queueTaskNum

    // 记录当前队列运行中的请求数
    this.StoreService.queueStatus.value.runningNum = this.running
    // 记录当前队列最大并发数
    this.StoreService.queueStatus.value.concurrency = this.concurrency
    // 记录已暂停文件数
    this.StoreService.queueStatus.value.pausedFileNum = isPausedCount
    // 记录已暂停任务数
    this.StoreService.queueStatus.value.pausedTaskNum = isPausedTaskCount
    // 记录等待中文件数
    // Store.queueStatus.waitingFileNum = isActiveCount

    // 记录等待中任务数
    this.StoreService.queueStatus.value.waitingTaskNum = isActiveTaskCount
    // 记录已完成文件数
    // Store.queueStatus.completedFileNum = this.successTasks.length
    // 记录已完成任务数
    this.StoreService.queueStatus.value.completedTaskNum = this.successTasks.length
    // 记录失败文件数
    // Store.queueStatus.failedFileNum = this.failedTasks.length
    // 记录失败任务数
    this.StoreService.queueStatus.value.failedTaskNum = this.failedTasks.length
    // 记录当前队列分片大小
    this.StoreService.queueStatus.value.chunkSize = this.chunkSize
  }

  /**
   * 添加请求到队列
   * @param task 任务
   * @param taskId 任务id
   * @param groupId 任务组id
   */
  addTask(tasks: any[], groupId: string) {
    // debugger
    return new Promise((resolve, reject) => {
      // Store.queueStatus.totalRequests = this.total

      this.taskGroups.set(groupId, {
        groupStatus: 'active', // 任务组状态 active活跃 | paused暂停
        tasks: tasks.map((taskItem) => ({
          task: taskItem.task, // 任务
          taskId: taskItem.taskId, // 任务id
          groupId, // 任务组id
          retries: 0, // 重试次数
          taskStatus: 'pending', // pending | running | success | failed
        })),
      })
      // 将任务添加到主队列
      tasks.forEach((task) => {
        this.queue.push({ groupId, task })
      })
      // 更新队列状态
      this.updateQueueStatus()
      // debugger
      resolve(true)
    })
  }
  // 删除指定任务组
  delTask(groupId: string) {
    debugger
    if (this.queue.length === 0) return
    this.queue.forEach((i) => {
      if (i.groupId === groupId) {
        this.queue.splice(this.queue.indexOf(i), 1)
      }
    })
  }

  // 开始执行队列
  start() {
    // if (this.isPaused) return
    while (this.running < this.concurrency && this.queue.length > 0) {
      const taskItem = this.queue.shift()
      const groupId = taskItem.groupId
      const currentTaskGroup = this.taskGroups.get(groupId)

      // 跳过暂停的任务组
      if (currentTaskGroup.groupStatus === 'paused') {
        // debugger
        continue
      }

      // 找到具体任务对象
      const taskObj = currentTaskGroup.tasks.find((t: any) => t.taskId === taskItem.task.taskId)
      // 跳过成功或失败或运行中的任务
      if (!taskObj || taskObj.taskStatus !== 'pending') {
        // debugger
        continue
      }

      this.running++

      taskObj.taskStatus = 'running'
      // debugger
      const aaa = this.executeTask(taskObj.task, groupId)
      aaa
        .then((res) => this.handleTaskSuccess(res, taskObj, groupId))
        .catch((err) => this.handleTaskFailure(err, taskObj, groupId))
    }
  }

  // 执行单个任务
  async executeTask(task: any, groupId: string) {
    if (!task) {
      throw new Error('对列执行：当前任务不存在')
    }
    return task()
  }

  // 处理任务成功
  handleTaskSuccess(res: any, taskObj: any, groupId: string) {
    // debugger
    this.running--
    taskObj.taskStatus = 'success'
    this.successTasks.push(taskObj)
    this.updateQueueStatus()
    this.checkGroupCompletion(groupId)
    this.start() // 继续执行队列
  }

  // 处理任务失败
  handleTaskFailure(err: any, taskObj: any, groupId: string) {
    // debugger
    this.running--
    taskObj.retries++
    this.updateQueueStatus()
    if (taskObj.retries > 3) {
      taskObj.taskStatus = 'failed'
      this.failedTasks.push(taskObj)
      this.checkGroupCompletion(groupId)
    } else {
      taskObj.taskStatus = 'pending'
      // 重试任务加入队列头部（优先处理）
      this.LogService.addLog(`分片 ${taskObj.task.taskId} 上传失败`, 'error')
      console.log('重试任务加入队列头部（优先处理）', groupId, taskObj.data)
      this.queue.unshift({ groupId, task: taskObj })
    }

    this.start() // 继续执行队列
  }

  // 检查任务组是否完成
  checkGroupCompletion(groupId: string) {
    
    const taskGroup = this.taskGroups.get(groupId)
    if (!taskGroup) return

    const allCompleted = taskGroup.tasks.every(
      (task: any) => task.taskStatus === 'success' || task.taskStatus === 'failed',
    )

    if (allCompleted) {
      debugger
      // 更新队列状态为：已完成
      taskGroup.taskStatus = 'completed'
      // 更新文件状态为 合并中
      this.StoreService.updateFileStatus('merge', groupId)
      // 触发文件分片上传成功钩子
      // this.Hooks.executeHook('onChunkUploaded', {uploadedChunkCount: taskGroup.tasks.length})
      
      // 5. 合并分片请求
      this.RequestService.mergeChunk(groupId, this.Hooks, this.LogService, this.StoreService)
      // 任务列表为空时，文件选择 解锁
      // if (this.queue.length === 0) {
      //   debugger
      //   Store.isUpLoading = false
      // }
      // this.completedCallback?.() // 触发完成回调
    }
  }

  /**
   * 暂停整个队列
   */
  pauseAll() {
    for (const [groupId] of this.taskGroups) {
      this.pauseGroup(groupId)
    }
  }

  /**
   * 恢复整个队列
   */
  resumeAll() {
    for (const [groupId] of this.taskGroups) {
      this.resumeGroup(groupId)
    }
  }

  /**
   * 暂停特定任务组
   * @param {string} groupId 任务组ID
   */
  pauseGroup(groupId: string) {
    debugger
    const taskGroup = this.taskGroups.get(groupId)
    if (taskGroup && taskGroup.groupStatus === 'active') {
      taskGroup.groupStatus = 'paused'
      this.StoreService.updateFileStatus('paused', groupId)
    }
  }

  /**
   * 恢复特定任务组
   * @param {string} groupId 任务组ID
   */
  resumeGroup(groupId: string) {
    debugger
    const taskGroup = this.taskGroups.get(groupId)
    if (taskGroup && taskGroup.groupStatus === 'paused') {
      taskGroup.groupStatus = 'active'
      this.StoreService.updateFileStatus('uploading', groupId)
      // 将该组所有未完成任务重新加入队列
      taskGroup.tasks.forEach((taskObj: any) => {
        if (taskObj.taskStatus === 'pending') {
          this.queue.unshift({ groupId, task: taskObj })
        }
      })

      this.start() // 恢复队列执行
    }
  }

  // 获取成功任务列表
  getSuccessfulTasks() {
    return this.successTasks
  }

  // 获取失败任务列表
  getFailedTasks() {
    return this.failedTasks
  }

  // 获取任务组状态
  getGroupStatus(groupId: string) {
    const group = this.taskGroups.get(groupId)
    return group ? group.groupStatus : null
  }

  // 重置队列
  resetAll() {
    debugger
    // resetStore()
    this.running = 0
    this.queue = []
    this.taskGroups.clear()
    this.successTasks = []
    this.failedTasks = []
    this.LogList = []
  }

  // 注册完成回调
  onComplete(callback: () => void) {
    // this.completedCallback = callback
  }

  // 获取状态文本
  /* getStatusText(status: string) {
    switch (status) {
      case 'pending':
        return '等待中'
      case 'in-progress':
        return '执行中'
      case 'completed':
        return '已完成'
      default:
        return '未知状态'
    }
  } */
  // 添加日志
  addLog(message: string) {
    const now = new Date()
    const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`

    this.LogList.unshift(`[${timeString}] ${message}`)
  }
}

export default Queue
export type { Queue }
